package ace.tool.generate.code.impl.manager;

import ace.tool.generate.code.impl.generator.DefaultGenerator;
import ace.tool.generate.code.impl.manager.common.EntityModelManager;
import ace.tool.generate.code.impl.manager.core.CoreProjectTestManager;
import ace.tool.generate.code.impl.resolver.scheme.model.bo.GenerateContext;
import ace.tool.generate.code.impl.resolver.scheme.model.bo.api.ApiClassInfo;
import ace.tool.generate.code.impl.resolver.scheme.model.bo.api.DtoClassInfo;
import ace.tool.generate.code.impl.resolver.scheme.model.bo.core.AggregateClassInfo;
import ace.tool.generate.code.impl.resolver.scheme.model.bo.core.AggregateImplClassInfo;
import ace.tool.generate.code.impl.resolver.scheme.model.bo.core.ApiImplClassInfo;
import ace.tool.generate.code.impl.resolver.scheme.model.bo.core.CoreAutoConfigClassInfo;
import ace.tool.generate.code.impl.resolver.scheme.model.bo.core.CoreBootstrapScannerClassInfo;
import ace.tool.generate.code.impl.resolver.scheme.model.bo.core.CoreConstantClassInfo;
import ace.tool.generate.code.impl.resolver.scheme.model.bo.core.EntityClassInfo;
import ace.tool.generate.code.impl.resolver.scheme.model.bo.core.GraphqlAdminControllerClassInfo;
import ace.tool.generate.code.impl.resolver.scheme.model.bo.core.InitListenerClassInfo;
import ace.tool.generate.code.impl.resolver.scheme.model.bo.core.InitServiceClassInfo;
import ace.tool.generate.code.impl.resolver.scheme.model.bo.core.InitServiceImplClassInfo;
import ace.tool.generate.code.impl.resolver.scheme.model.bo.core.ManagerClassInfo;
import ace.tool.generate.code.impl.resolver.scheme.model.bo.core.ManagerImplClassInfo;
import ace.tool.generate.code.impl.resolver.scheme.model.bo.core.PropertiesClassInfo;
import ace.tool.generate.code.impl.resolver.scheme.model.bo.core.RepositoryClassInfo;
import ace.tool.generate.code.impl.resolver.scheme.model.bo.core.RepositoryScannerClassInfo;
import ace.tool.generate.code.impl.resolver.scheme.model.bo.core.RestAdminControllerClassInfo;
import ace.tool.generate.code.impl.resolver.scheme.model.bo.core.RestRpcControllerClassInfo;
import ace.tool.generate.code.impl.resolver.scheme.model.bo.core.RestTenantAdminControllerClassInfo;
import ace.tool.generate.code.impl.resolver.scheme.model.bo.core.resources.GraphqlDtoFileInfo;
import ace.tool.generate.code.impl.resolver.scheme.model.bo.core.resources.GraphqlInputFileInfo;
import ace.tool.generate.code.impl.resolver.scheme.model.bo.core.resources.LiquibaseTableFileInfo;
import ace.tool.generate.code.impl.resolver.scheme.model.bo.sdk.FeignClassInfo;
import java.util.HashMap;
import java.util.Map;
import lombok.SneakyThrows;

/**
 * @author caspar
 * @date 2024/1/11 10:12 core project manager generator
 */
public class CoreProjectManager {

  private final GenerateContext context;
  private final EntityModelManager entityModelManager = new EntityModelManager();

  public CoreProjectManager(GenerateContext context) {
    this.context = context;
  }

  @SneakyThrows
  public void generate() {

    this.generatePom();

    this.generateReadme();

    this.generateResourcesSpringFactories();

    this.generateResourcesAutoConfigurationImports();

    this.generateLiquibaseInitTableXml();

    this.generateLiquibaseTableXmlList();

    this.generateGraphqlSchemaFile();

    this.generateGraphqlSchemaAutoGenerateFile();

    this.generateGraphqlDtoFiles();

    this.generateGraphqlInputFiles();

    this.generateCoreAutoConfigClass();

    this.generateCoreBootstrapScannerClass();

    this.generateCoreConstantClass();

    this.generateDaoEntities();

    this.generateDaoRepositories();

    this.generateDaoRepositoryScanner();

    this.generateAggregates();

    this.generateAggregateImpls();

    this.generateManagers();

    this.generateManagerImpls();

    this.generateInitService();

    this.generateInitServiceImpl();

    this.generateProperties();

    this.generateInitListener();

    this.generateGraphqlAdminControllers();

    this.generateRestAdminControllers();

    this.generateRestRpcControllers();

    this.generateApiImpls();

    this.generateTest();
  }


  private void generateAggregates() {
    context
        .getModuleProject()
        .getCoreProject()
        .getAggregateClassInfos()
        .forEach(this::generateAggregate);
  }

  private void generateAggregate(AggregateClassInfo aggregateClassInfo) {
    EntityClassInfo entityClassInfo =
        this.entityModelManager.getEntityClassInfoByEntityModelId(
            context, aggregateClassInfo.getEntityModelId());
    Map<String, Object> model = new HashMap<>();
    model.put("packageFullName", aggregateClassInfo.getInfo().getClassPackageFullName());
    model.put("entityClassFullName", entityClassInfo.getInfo().getClassFullName());
    model.put("remark", entityClassInfo.getModel().getRemark());
    model.put("className", aggregateClassInfo.getInfo().getClassName());

    String templateFile = "/schema/core-project/main/java/core/impl/dao/aggregate/CoreProjectAggregate.ftl";
    String outputFileFullName = aggregateClassInfo.getInfo().getClassFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName).generate(model);
  }

  private void generateAggregateImpls() {
    context
        .getModuleProject()
        .getCoreProject()
        .getAggregateImplClassInfos()
        .forEach(this::generateAggregateImpl);
  }

  private void generateAggregateImpl(AggregateImplClassInfo aggregateImplClassInfo) {
    EntityClassInfo entityClassInfo = this.entityModelManager.getEntityClassInfoByEntityModelId(
        context, aggregateImplClassInfo.getEntityModelId()
    );

    AggregateClassInfo aggregateClassInfo = this.entityModelManager.getAggregateClassInfoByEntityModelId(
        context.getModuleProject().getCoreProject().getAggregateClassInfos(),
        aggregateImplClassInfo.getEntityModelId()
    );

    Map<String, Object> model = new HashMap<>();
    model.put("packageFullName", aggregateImplClassInfo.getInfo().getClassPackageFullName());
    model.put("entityClassFullName", entityClassInfo.getInfo().getClassFullName());
    model.put("aggregateClassFullName", aggregateClassInfo.getInfo().getClassFullName());
    model.put("className", aggregateImplClassInfo.getInfo().getClassName());
    model.put("aggregateClassName", aggregateClassInfo.getInfo().getClassName());
    model.put("remark", entityClassInfo.getModel().getRemark());

    String templateFile = "/schema/core-project/main/java/core/impl/dao/aggregate/impl/CoreProjectAggregateImpl.ftl";
    String outputFileFullName = aggregateImplClassInfo.getInfo().getClassFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName).generate(model);
  }

  private void generateCoreConstantClass() {
    CoreConstantClassInfo coreConstantClassInfo = context.getModuleProject().getCoreProject().getCoreConstantClassInfo();

    Map<String, Object> model = new HashMap<>();
    model.put("packageFullName", coreConstantClassInfo.getInfo().getClassPackageFullName());
    model.put("className", coreConstantClassInfo.getInfo().getClassName());
    model.put("dsName", coreConstantClassInfo.getDsName());

    String templateFile = "/schema/core-project/main/java/core/impl/constant/CoreProjectConstantClass.ftl";
    String outputFileFullName = coreConstantClassInfo.getInfo().getClassFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName).generate(model);
  }

  private void generateTest() {
    new CoreProjectTestManager(context).generate();
  }

  private void generateApiImpls() {
    context
        .getModuleProject()
        .getCoreProject()
        .getApiImplClassInfos()
        .forEach(this::generateApiImpl);
  }

  private void generateApiImpl(ApiImplClassInfo apiImplClassInfo) {

    Map<String, Object> model = new HashMap<>();
    model.put("info", apiImplClassInfo.getInfo());
    model.put("dtoInfo", apiImplClassInfo.getDtoClassInfo().getInfo());
    model.put("apiInfo", apiImplClassInfo.getApiClassInfo().getInfo());
    model.put("entityInfo", apiImplClassInfo.getEntityClassInfo().getInfo());
    model.put("managerInfo", apiImplClassInfo.getManagerClassInfo().getInfo());
    model.put("remark", apiImplClassInfo.getEntityClassInfo().getModel().getRemark());
    model.put("idType", apiImplClassInfo.getEntityClassInfo().getModel().getEntityIdType());

    String templateFile = "/schema/core-project/main/java/core/impl/api/impl/ApiImpl.ftl";
    String outputFileFullName = apiImplClassInfo.getInfo().getClassFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName).generate(model);
  }

  private void generateRestRpcControllers() {
    context
        .getModuleProject()
        .getCoreProject()
        .getRestRpcControllerClassInfos()
        .forEach(this::generateRestRpcController);
  }

  private void generateRestRpcController(RestRpcControllerClassInfo restRpcControllerClassInfo) {
    EntityModelManager entityModelManager = new EntityModelManager();
    EntityClassInfo entityClassInfo = entityModelManager.getEntityClassInfoByEntityModelId(context, restRpcControllerClassInfo.getEntityModelId());
    DtoClassInfo dtoClassInfo = entityModelManager.getDtoClassInfoByEntityModelId(context, restRpcControllerClassInfo.getEntityModelId());
    FeignClassInfo feignClassInfo = entityModelManager.getFeignClassInfoByEntityModelId(context, restRpcControllerClassInfo.getEntityModelId());
    ApiClassInfo apiClassInfo = entityModelManager.getApiClassInfoByEntityModelId(context, restRpcControllerClassInfo.getEntityModelId());

    Map<String, Object> model = new HashMap<>();
    model.put("packageFullName", restRpcControllerClassInfo.getInfo().getClassPackageFullName());
    model.put("dtoClassFullName", dtoClassInfo.getInfo().getClassFullName());
    model.put("dtoClassName", dtoClassInfo.getInfo().getClassName());
    model.put("entityClassFullName", entityClassInfo.getInfo().getClassFullName());
    model.put("feignClassFullName", feignClassInfo.getInfo().getClassFullName());
    model.put("entityClassRemark", entityClassInfo.getModel().getRemark());
    model.put("className", restRpcControllerClassInfo.getInfo().getClassName());
    model.put("entityClassName", entityClassInfo.getInfo().getClassName());
    model.put("entityIdType", entityClassInfo.getModel().getEntityIdType());
    model.put("feignClassName", feignClassInfo.getInfo().getClassName());
    model.put("restNamespace", restRpcControllerClassInfo.getRestNamespace());
    model.put("entityClassNameLowercaseDashName", entityClassInfo.getModel().getEntityClassNameLowercaseDashName());
    model.put("apiInfo", apiClassInfo.getInfo());

    String templateFile = "/schema/core-project/main/java/core/impl/controller/rest/rpc/CoreProjectRpcRestController.ftl";
    String outputFileFullName = restRpcControllerClassInfo.getInfo().getClassFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName).generate(model);
  }

  private void generateRestTenantAdminControllers() {
    context
        .getModuleProject()
        .getCoreProject()
        .getRestTenantAdminControllerClassInfos()
        .forEach(this::generateRestTenantAdminController);
  }

  private void generateRestTenantAdminController(
      RestTenantAdminControllerClassInfo restTenantAdminControllerClassInfo) {

    String templateFile = "/schema/core-project/main/java/core/impl/controller/rest/admin/CoreProjectTenantAdminController.ftl";
    String outputFileFullName = restTenantAdminControllerClassInfo.getInfo().getClassFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName).generate(restTenantAdminControllerClassInfo);
  }

  private void generateRestAdminControllers() {
    context
        .getModuleProject()
        .getCoreProject()
        .getRestAdminControllerClassInfos()
        .forEach(this::generateRestAdminController);
  }

  private void generateRestAdminController(
      RestAdminControllerClassInfo restAdminControllerClassInfo) {
    EntityModelManager entityModelManager = new EntityModelManager();
    EntityClassInfo entityClassInfo =
        entityModelManager.getEntityClassInfoByEntityModelId(
            context, restAdminControllerClassInfo.getEntityModelId());

    Map<String, Object> model = new HashMap<>();
    model.put("packageFullName", restAdminControllerClassInfo.getInfo().getClassPackageFullName());
    model.put("entityClassFullName", entityClassInfo.getInfo().getClassFullName());
    model.put("entityClassRemark", entityClassInfo.getModel().getRemark());
    model.put("className", restAdminControllerClassInfo.getInfo().getClassName());
    model.put("entityClassName", entityClassInfo.getInfo().getClassName());
    model.put("entityIdType", entityClassInfo.getModel().getEntityIdType());
    model.put("restNamespace", restAdminControllerClassInfo.getRestNamespace());
    model.put(
        "entityClassNameLowercaseDashName",
        entityClassInfo.getModel().getEntityClassNameLowercaseDashName());

    String templateFile = "/schema/core-project/main/java/core/impl/controller/rest/admin/CoreProjectAdminController.ftl";
    String outputFileFullName = restAdminControllerClassInfo.getInfo().getClassFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName).generate(model);
  }

  private void generateGraphqlAdminControllers() {
    context
        .getModuleProject()
        .getCoreProject()
        .getGraphqlAdminControllerClassInfos()
        .forEach(this::generateGraphqlAdminController);
  }

  private void generateGraphqlAdminController(
      GraphqlAdminControllerClassInfo graphqlAdminControllerClassInfo) {
    EntityModelManager entityModelManager = new EntityModelManager();
    Map<String, Object> model = new HashMap<>();
    EntityClassInfo entityClassInfo =
        entityModelManager.getEntityClassInfoByEntityModelId(
            context, graphqlAdminControllerClassInfo.getEntityModelId());
    model.put(
        "packageFullName", graphqlAdminControllerClassInfo.getInfo().getClassPackageFullName());
    model.put("entityClassFullName", entityClassInfo.getInfo().getClassFullName());
    model.put("schemaExtendMapping", graphqlAdminControllerClassInfo.getSchemaExtendMapping());
    model.put("className", graphqlAdminControllerClassInfo.getInfo().getClassName());
    model.put("entityClassName", entityClassInfo.getInfo().getClassName());
    model.put("entityIdType", entityClassInfo.getModel().getEntityIdType());

    String templateFile = "/schema/core-project/main/java/core/impl/controller/graphql/admin/CoreProjectAdminGraphql.ftl";
    String outputFileFullName = graphqlAdminControllerClassInfo.getInfo().getClassFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName).generate(model);
  }

  private void generateInitListener() {
    Map<String, Object> model = new HashMap<>();
    InitListenerClassInfo classInfo =
        context.getModuleProject().getCoreProject().getInitListenerClassInfo();
    InitServiceClassInfo initServiceClassInfo =
        context.getModuleProject().getCoreProject().getInitServiceClassInfo();
    model.put("packageFullName", classInfo.getInfo().getClassPackageFullName());
    model.put("className", classInfo.getInfo().getClassName());
    model.put("initServiceClassFullName", initServiceClassInfo.getInfo().getClassFullName());
    model.put("initServiceClassName", initServiceClassInfo.getInfo().getClassName());
    String templateFile = "/schema/core-project/main/java/core/impl/listener/CoreProjectInitListener.ftl";
    String outputFileFullName = classInfo.getInfo().getClassFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName).generate(model);
  }

  private void generateProperties() {
    Map<String, Object> model = new HashMap<>();
    PropertiesClassInfo classInfo =
        context.getModuleProject().getCoreProject().getPropertiesClassInfo();
    model.put("packageFullName", classInfo.getInfo().getClassPackageFullName());
    model.put("className", classInfo.getInfo().getClassName());
    model.put("configPrefix", classInfo.getConfigPrefix());
    String templateFile = "/schema/core-project/main/java/core/impl/properties/CoreProjectProperties.ftl";
    String outputFileFullName = classInfo.getInfo().getClassFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName).generate(model);
  }

  private void generateInitServiceImpl() {
    Map<String, Object> model = new HashMap<>();
    InitServiceImplClassInfo classInfo =
        context.getModuleProject().getCoreProject().getInitServiceImplClassInfo();
    InitServiceClassInfo initServiceClassInfo =
        context.getModuleProject().getCoreProject().getInitServiceClassInfo();
    model.put("packageFullName", classInfo.getInfo().getClassPackageFullName());
    model.put("initServiceClassFullName", initServiceClassInfo.getInfo().getClassFullName());
    model.put("className", classInfo.getInfo().getClassName());
    model.put("initServiceClassName", initServiceClassInfo.getInfo().getClassName());
    String templateFile = "/schema/core-project/main/java/core/impl/service/impl/CoreProjectInitServiceImplClass.ftl";
    String outputFileFullName = classInfo.getInfo().getClassFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName).generate(model);
  }

  private void generateInitService() {
    Map<String, Object> model = new HashMap<>();
    InitServiceClassInfo classInfo =
        context.getModuleProject().getCoreProject().getInitServiceClassInfo();
    model.put("packageFullName", classInfo.getInfo().getClassPackageFullName());
    model.put("className", classInfo.getInfo().getClassName());
    String templateFile = "/schema/core-project/main/java/core/impl/service/CoreProjectInitServiceClass.ftl";
    String outputFileFullName = classInfo.getInfo().getClassFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName).generate(model);
  }

  private void generateManagerImpls() {
    context
        .getModuleProject()
        .getCoreProject()
        .getManagerImplClassInfos()
        .forEach(this::generateManagerImpl);
  }

  private void generateManagerImpl(ManagerImplClassInfo managerImplClassInfo) {
    EntityModelManager entityModelManager = new EntityModelManager();
    Map<String, Object> model = new HashMap<>();
    EntityClassInfo entityClassInfo =
        entityModelManager.getEntityClassInfoByEntityModelId(
            context, managerImplClassInfo.getEntityModelId());
    DtoClassInfo dtoClassInfo =
        entityModelManager.getDtoClassInfoByEntityModelId(
            context, managerImplClassInfo.getEntityModelId());
    ManagerClassInfo managerClassInfo =
        entityModelManager.getManagerClassInfoByEntityModelId(
            context, managerImplClassInfo.getEntityModelId());
    model.put("packageFullName", managerImplClassInfo.getInfo().getClassPackageFullName());
    model.put("entityClassFullName", entityClassInfo.getInfo().getClassFullName());
    model.put("dtoClassFullName", dtoClassInfo.getInfo().getClassFullName());
    model.put("managerClassFullName", managerClassInfo.getInfo().getClassFullName());
    model.put("remark", entityClassInfo.getModel().getRemark());
    model.put("className", managerImplClassInfo.getInfo().getClassName());
    model.put("entityClassName", entityClassInfo.getInfo().getClassName());
    model.put("entityIdType", entityClassInfo.getModel().getEntityIdType());
    model.put("dtoClassName", dtoClassInfo.getInfo().getClassName());
    model.put("managerClassName", managerClassInfo.getInfo().getClassName());
    model.put("source", managerImplClassInfo);
    model.put("extendClassName", managerImplClassInfo.getExtendClassName());
    String templateFile = "/schema/core-project/main/java/core/impl/manager/impl/CoreProjectManagerImpl.ftl";
    String outputFileFullName = managerImplClassInfo.getInfo().getClassFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName).generate(model);
  }

  private void generateManagers() {
    context
        .getModuleProject()
        .getCoreProject()
        .getManagerClassInfos()
        .forEach(this::generateManager);
  }

  private void generateManager(ManagerClassInfo managerClassInfo) {
    EntityModelManager entityModelManager = new EntityModelManager();
    Map<String, Object> model = new HashMap<>();
    EntityClassInfo entityClassInfo =
        entityModelManager.getEntityClassInfoByEntityModelId(
            context, managerClassInfo.getEntityModelId());
    DtoClassInfo dtoClassInfo =
        entityModelManager.getDtoClassInfoByEntityModelId(
            context, managerClassInfo.getEntityModelId());
    model.put("packageFullName", managerClassInfo.getInfo().getClassPackageFullName());
    model.put("entityClassFullName", entityClassInfo.getInfo().getClassFullName());
    model.put("dtoClassFullName", dtoClassInfo.getInfo().getClassFullName());
    model.put("remark", entityClassInfo.getModel().getRemark());
    model.put("className", managerClassInfo.getInfo().getClassName());
    model.put("entityClassName", entityClassInfo.getInfo().getClassName());
    model.put("entityIdType", entityClassInfo.getModel().getEntityIdType());
    model.put("dtoClassName", dtoClassInfo.getInfo().getClassName());
    model.put("source", managerClassInfo);
    model.put("extendIfcName", managerClassInfo.getExtendIfcName());
    String templateFile = "/schema/core-project/main/java/core/impl/manager/CoreProjectManager.ftl";
    String outputFileFullName = managerClassInfo.getInfo().getClassFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName).generate(model);
  }

  private void generateDaoRepositoryScanner() {
    RepositoryScannerClassInfo repositoryScannerClassInfo =
        context.getModuleProject().getCoreProject().getRepositoryScannerClassInfo();
    Map<String, Object> model = new HashMap<>();
    model.put("packageFullName", repositoryScannerClassInfo.getInfo().getClassPackageFullName());
    model.put("className", repositoryScannerClassInfo.getInfo().getClassName());
    String templateFile = "/schema/core-project/main/java/core/impl/dao/repository/CoreProjectDaoEntityRepositoryScannerClass.ftl";
    String outputFileFullName = repositoryScannerClassInfo.getInfo().getClassFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName).generate(model);
  }

  private void generateDaoRepositories() {
    context
        .getModuleProject()
        .getCoreProject()
        .getRepositoryClassInfos()
        .forEach(this::generateDaoRepository);
  }

  private void generateDaoRepository(RepositoryClassInfo repositoryClassInfo) {
    EntityModelManager entityModelManager = new EntityModelManager();
    Map<String, Object> model = new HashMap<>();
    EntityClassInfo entityClassInfo =
        entityModelManager.getEntityClassInfoByEntityModelId(
            context, repositoryClassInfo.getEntityModelId());
    model.put("packageFullName", repositoryClassInfo.getInfo().getClassPackageFullName());
    model.put("className", repositoryClassInfo.getInfo().getClassName());
    model.put("entityClassFullName", entityClassInfo.getInfo().getClassFullName());
    model.put("entityClassName", entityClassInfo.getInfo().getClassName());
    model.put("remark", entityClassInfo.getModel().getRemark());
    model.put("entityIdType", entityClassInfo.getModel().getEntityIdType());
    model.put("coreConstantsDsName", repositoryClassInfo.getDsName());
    model.put(
        "coreConstantsClassFullName",
        context
            .getModuleProject()
            .getCoreProject()
            .getCoreConstantClassInfo()
            .getInfo()
            .getClassFullName());
    String templateFile = "/schema/core-project/main/java/core/impl/dao/repository/CoreProjectDaoEntityRepository.ftl";
    String outputFileFullName = repositoryClassInfo.getInfo().getClassFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName).generate(model);
  }

  private void generateDaoEntities() {
    context
        .getModuleProject()
        .getCoreProject()
        .getEntityClassInfos()
        .forEach(this::generateDaoEntity);
  }

  private void generateDaoEntity(EntityClassInfo entityClassInfo) {

    Map<String, Object> model = new HashMap<>();
    model.put("packageFullName", entityClassInfo.getInfo().getClassPackageFullName());
    model.put("dtoClassInfo", entityClassInfo.getDtoClassInfo());
    model.put("remark", entityClassInfo.getModel().getRemark());
    model.put("tableName", entityClassInfo.getModel().getTableName());
    model.put("className", entityClassInfo.getModel().getClassName());
    model.put("entityIdType", entityClassInfo.getModel().getEntityIdType());
    model.put("fields", entityClassInfo.getModel().getFields());
    String templateFile = "/schema/core-project/main/java/core/impl/dao/entity/CoreProjectDaoEntity.ftl";
    String outputFileFullName = entityClassInfo.getInfo().getClassFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName).generate(model);
  }

  private void generateCoreBootstrapScannerClass() {
    Map<String, Object> model = new HashMap<>();
    CoreBootstrapScannerClassInfo coreBootstrapScannerClassInfo =
        context.getModuleProject().getCoreProject().getCoreBootstrapScannerClassInfo();
    model.put("packageFullName", coreBootstrapScannerClassInfo.getInfo().getClassPackageFullName());
    model.put("className", coreBootstrapScannerClassInfo.getInfo().getClassName());
    String templateFile = "/schema/core-project/main/java/core/impl/CoreProjectBootstrapScannerClass.ftl";
    String outputFileFullName =
        context
            .getModuleProject()
            .getCoreProject()
            .getCoreBootstrapScannerClassInfo()
            .getInfo()
            .getClassFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName).generate(model);
  }

  private void generateCoreAutoConfigClass() {
    Map<String, Object> model = new HashMap<>();
    CoreAutoConfigClassInfo coreAutoConfigClassInfo =
        context.getModuleProject().getCoreProject().getCoreAutoConfigClassInfo();
    CoreBootstrapScannerClassInfo coreBootstrapScannerClassInfo =
        context.getModuleProject().getCoreProject().getCoreBootstrapScannerClassInfo();
    RepositoryScannerClassInfo repositoryScannerClassInfo =
        context.getModuleProject().getCoreProject().getRepositoryScannerClassInfo();
    PropertiesClassInfo propertiesClassInfo =
        context.getModuleProject().getCoreProject().getPropertiesClassInfo();
    model.put("packageFullName", coreAutoConfigClassInfo.getInfo().getClassPackageFullName());
    model.put(
        "coreBoostrapScannerClassFullName",
        coreBootstrapScannerClassInfo.getInfo().getClassFullName());
    model.put(
        "repositoryScannerClassFullName", repositoryScannerClassInfo.getInfo().getClassFullName());
    model.put("modulePropertiesClassFullName", propertiesClassInfo.getInfo().getClassFullName());
    model.put(
        "coreBoostrapScannerClassName", coreBootstrapScannerClassInfo.getInfo().getClassName());
    model.put("modulePropertiesClassName", propertiesClassInfo.getInfo().getClassName());
    model.put("repositoryScannerClassName", repositoryScannerClassInfo.getInfo().getClassName());
    model.put("className", coreAutoConfigClassInfo.getInfo().getClassName());
    model.put(
        "projectModuleName",
        context.getModuleProject().getCoreProject().getInfo().getProjectModuleName());
    model.put(
        "projectModuleDisplayName",
        context.getModuleProject().getCoreProject().getInfo().getProjectModuleDisplayName());
    String templateFile = "/schema/core-project/main/java/autoconfig/CoreProjectAutoConfigClass.ftl";
    String outputFileFullName =
        context
            .getModuleProject()
            .getCoreProject()
            .getCoreAutoConfigClassInfo()
            .getInfo()
            .getClassFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName).generate(model);
  }

  private void generateGraphqlInputFiles() {
    context
        .getModuleProject()
        .getCoreProject()
        .getGraphqlInputFileInfos()
        .forEach(this::generateGraphqlInputFile);
  }

  private void generateGraphqlInputFile(GraphqlInputFileInfo graphqlInputFileInfo) {
    Object model = graphqlInputFileInfo.getModel();
    String templateFile = "/schema/core-project/main/resources/graphql/input/CoreProjectGraphqlInput.ftl";
    String outputFileFullName = graphqlInputFileInfo.getFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName).generate(model);
  }

  private void generateGraphqlDtoFiles() {
    context
        .getModuleProject()
        .getCoreProject()
        .getGraphqlDtoFileInfos()
        .forEach(this::generateGraphqlDtoFile);
  }

  private void generateGraphqlDtoFile(GraphqlDtoFileInfo graphqlDtoFileInfo) {
    Object model = graphqlDtoFileInfo.getModel();
    String templateFile = "/schema/core-project/main/resources/graphql/dto/CoreProjectGraphqlDto.ftl";
    String outputFileFullName = graphqlDtoFileInfo.getFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName).generate(model);
  }

  private void generateGraphqlSchemaAutoGenerateFile() {
    Object model =
        context
            .getModuleProject()
            .getCoreProject()
            .getGraphqlSchemaAutoGenerateFileInfo()
            .getModel();
    String templateFile = "/schema/core-project/main/resources/graphql/CoreProjectGraphqlSchemaAutoGenerate.ftl";
    String outputFileFullName =
        context
            .getModuleProject()
            .getCoreProject()
            .getGraphqlSchemaAutoGenerateFileInfo()
            .getFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName).generate(model);
  }

  private void generateGraphqlSchemaFile() {
    // 因为空的结构文件,不能直接启动
    if (true) {
      return;
    }
    Map<String, Object> model = new HashMap<>();
    String templateFile = "/schema/core-project/main/resources/graphql/CoreProjectGraphqlSchema.ftl";
    String outputFileFullName =
        context.getModuleProject().getCoreProject().getGraphqlSchemaFileInfo().getFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName).generate(model);
  }

  private void generateLiquibaseTableXmlList() {
    context
        .getModuleProject()
        .getCoreProject()
        .getLiquibaseTableFileInfos()
        .forEach(this::generateLiquibaseTableXml);
  }

  private void generateLiquibaseTableXml(LiquibaseTableFileInfo liquibaseTableFileInfo) {
    Map<String, Object> model = new HashMap<>();
    String templateFile = "/schema/core-project/main/resources/db/changelog/tables/CoreProjectLiquibaseMysqlTable.ftl";
    String outputFileFullName = liquibaseTableFileInfo.getFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName)
        .generate(liquibaseTableFileInfo.getLiquibaseTemplateModel());
  }

  private void generateLiquibaseInitTableXml() {
    Map<String, Object> model = new HashMap<>();
    String templateFile = "/schema/core-project/main/resources/db/changelog/CoreProjectLiquibaseInitTableXml.ftl";
    String outputFileFullName =
        context
            .getModuleProject()
            .getCoreProject()
            .getLiquibaseInitTableFileInfo()
            .getFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName).generate(model);
  }

  private void generateResourcesAutoConfigurationImports() {
    Map<String, Object> model = new HashMap<>();
    model.put(
        "classFullNames",
        context
            .getModuleProject()
            .getCoreProject()
            .getAutoConfigurationImportsInfo()
            .getClassFullNameImports());
    String templateFile = "/schema/core-project/main/resources/META-INF/spring/CoreProjectAutoConfigurationImports.ftl";
    String outputFileFullName =
        context
            .getModuleProject()
            .getCoreProject()
            .getAutoConfigurationImportsInfo()
            .getFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName).generate(model);
  }

  private void generateResourcesSpringFactories() {
    Map<String, Object> model = new HashMap<>();
    model.put(
        "classFullNames",
        context
            .getModuleProject()
            .getCoreProject()
            .getSpringFactoriesInfo()
            .getClassFullNameImports());
    String templateFile = "/schema/core-project/main/resources/META-INF/CoreProjectSpringFactories.ftl";
    String outputFileFullName =
        context.getModuleProject().getCoreProject().getSpringFactoriesInfo().getFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName).generate(model);
  }

  private void generateReadme() {
    Map<String, String> model = new HashMap<>();
    String templateFile = "/schema/core-project/CoreProjectReadme.ftl";
    String outputFileFullName =
        context.getModuleProject().getCoreProject().getInfo().getReadmeFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName).generate(model);
  }

  private void generatePom() {
    Map<String, String> model = new HashMap<>();
    model.put("projectMavenArtifactId", context.getModuleProject().getInfo().getMavenArtifactId());
    model.put(
        "apiProjectMavenArtifactId",
        context.getModuleProject().getApiProject().getInfo().getMavenArtifactId());
    model.put(
        "coreProjectMavenArtifactId",
        context.getModuleProject().getCoreProject().getInfo().getMavenArtifactId());
    model.put(
        "sdkProjectMavenArtifactId",
        context.getModuleProject().getSdkProject().getInfo().getMavenArtifactId());

    String templateFile = "/schema/core-project/CoreProjectPom.ftl";
    String outputFileFullName =
        context.getModuleProject().getCoreProject().getInfo().getPomFileFullName();
    new DefaultGenerator(templateFile, outputFileFullName).generate(model);
  }
}
